package General.CropPic;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;

import com.hmyd.hmyd_android.R;
import com.hmyd.hmyd_android.ui.CropImageActivity;
import com.hmyd.hmyd_android.utils.Utils;

import General.CropPic.Listener.CropListener;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.content.ActivityNotFoundException;
import android.content.ContentUris;
import android.content.Context;
import android.content.Intent;
import android.content.pm.ActivityInfo;
import android.content.res.TypedArray;
import android.database.Cursor;
import android.graphics.Bitmap;
import android.graphics.drawable.BitmapDrawable;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.os.Environment;
import android.provider.DocumentsContract;
import android.provider.MediaStore;
import android.view.Gravity;
import android.view.KeyEvent;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.View.OnKeyListener;
import android.view.WindowManager;
import android.widget.PopupWindow;

public class PhotoGraph implements OnClickListener, OnKeyListener {

	private Activity mContext;
	private int mStyleId;
	private int mLayoutId;
	private boolean mIsCrop = true;

	private String resultFilepath;
	private PopupWindow popupWindow;
	private boolean mKeyCodeBack;// 监听返回按键
	private CropListener mListener;
	public int mOrienValue = ActivityInfo.SCREEN_ORIENTATION_PORTRAIT;

	private static final int REQUEST_TAKE_PHOTO = 2000;
	private static final int REQUEST_GALLERY_IMAGE = 2001;
	private static final int REQUEST_MODIFY_FINISH = 2003;

	public PhotoGraph(Activity context) {
		this(context, R.style.DivPhotoGraph, null);
	}

	public PhotoGraph(Activity context, int mStyleId) {
		this(context, mStyleId, null);
	}

	public PhotoGraph(Activity context, CropListener mListener) {
		this(context, R.style.DivPhotoGraph, mListener);
	}

	public PhotoGraph(Activity context, int mStyleId, CropListener mListener) {
		this.mContext = context;
		this.mStyleId = mStyleId;
		this.mListener = mListener;
		TypedArray a = context.obtainStyledAttributes(null, R.styleable.PhotoGraph,
				R.style.DivPhotoGraph, mStyleId);
		mLayoutId = a.getResourceId(R.styleable.PhotoGraph_graph_popup_layout_id,
				R.layout.photograph_pop);
		mKeyCodeBack = a.getBoolean(R.styleable.PhotoGraph_graph_keycode_back, true);
		mIsCrop = a.getBoolean(R.styleable.PhotoGraph_graph_iscrop, true);
		mOrienValue = a.getInteger(R.styleable.PhotoGraph_graph_orientation,
				ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
	}

	@Override
	public void onClick(View v) {
		if (v.getId() == R.id.pg_camera) {
			doTakePhoto();
		} else if (v.getId() == R.id.pg_gallery) {
			doPickPhotoFromGallery();
		} else if (v.getId() == R.id.pg_back) {
			dismiss();
		}
	}

	public void dismiss() {
		if (popupWindow != null && popupWindow.isShowing()) {
			popupWindow.dismiss();
		}
	}

	private Intent getTakePickIntent(File f) {
		Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
		intent.putExtra(MediaStore.EXTRA_SCREEN_ORIENTATION, mOrienValue);
		intent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(f));
		return intent;
	}

	/** 拍照 */
	private void doTakePhoto() {
		try {
			resultFilepath = Environment.getExternalStorageDirectory() + "/"
					+ mContext.getPackageName() + "/" + Utils.getTime() + ".jpg";
			File mCurrentPhotoFile = new File(resultFilepath);// 给新照的照片文件命名
			if (!mCurrentPhotoFile.getParentFile().exists())
				mCurrentPhotoFile.getParentFile().mkdirs();
			Intent intent = getTakePickIntent(mCurrentPhotoFile);
			mContext.startActivityForResult(intent, REQUEST_TAKE_PHOTO);
		} catch (ActivityNotFoundException e) {
			// MyLog.show(mContext, R.string.photograph_camera_error);
		}
	}

	/** 读取相册 */
	private void doPickPhotoFromGallery() {
		try {
			final Intent intent = PhotoPick.getPhotoPickIntent();
			mContext.startActivityForResult(
					Intent.createChooser(intent,
							mContext.getString(R.string.photograph_gallery_image)),
					REQUEST_GALLERY_IMAGE);
		} catch (ActivityNotFoundException e) {
			// MyLog.show(mContext, R.string.photograph_img_error);
		}
	}

	public void doPopup(int mViewId) {
		LayoutInflater inflater = (LayoutInflater) mContext
				.getSystemService(Activity.LAYOUT_INFLATER_SERVICE);
		View contentView = inflater.inflate(mLayoutId, null);
		contentView.setFocusableInTouchMode(true);
		contentView.setOnKeyListener(this);
		popupWindow = new PopupWindow(contentView, WindowManager.LayoutParams.FILL_PARENT,
				WindowManager.LayoutParams.FILL_PARENT);
		View b1 = (View) contentView.findViewById(R.id.pg_camera);
		if (b1 != null)
			b1.setOnClickListener(this);
		View b2 = (View) contentView.findViewById(R.id.pg_gallery);
		if (b2 != null)
			b2.setOnClickListener(this);
		View b3 = (View) contentView.findViewById(R.id.pg_back);
		if (b3 != null)
			b3.setOnClickListener(this);

		popupWindow.setBackgroundDrawable(new BitmapDrawable());// 必须设置背景，点击非触摸区域才会消失
		// 设置PopupWindow外部区域是否可触摸
		popupWindow.setFocusable(true); // 设置PopupWindow可获得焦点
		popupWindow.setTouchable(true); // 设置PopupWindow可触摸
		popupWindow.setOutsideTouchable(false); // 设置非PopupWindow区域可触摸
		popupWindow.showAtLocation(mContext.findViewById(mViewId), Gravity.BOTTOM
				| Gravity.CENTER_HORIZONTAL, 0, 0);
	}

	public void onActivityResult(int requestCode, int resultCode, Intent data) {
		if (resultCode != Activity.RESULT_OK) {
			// MyLog.d(PhotoGraph.class, "user canceled.");
			return;
		}

		switch (requestCode) {
		case REQUEST_TAKE_PHOTO:
			if (mIsCrop && doClipPhoto()) {
				return;
			}
			break;
		case REQUEST_GALLERY_IMAGE:
			if (null == data) {
				// MyLog.d(PhotoPick.class, "data fail.");
				return;
			}
			// resultFilepath = getGalleryImagePath(data);
			resultFilepath = getPath(mContext, data.getData());
			if (mIsCrop && doClipPhoto()) {
				return;
			}

			break;
		case REQUEST_MODIFY_FINISH:
			// 裁剪结束
			if (data != null) {
				resultFilepath = data.getStringExtra("path");
			}
			if (resultFilepath != null && resultFilepath.length() > 0
					&& new File(resultFilepath).exists()) {
				// MyLog.d(PhotoPick.class, "data updateImg.");
				updateImg();
				return;
			}

			if (null == data) {
				// MyLog.d(PhotoPick.class, "data fail.");
				return;
			}
			doImg(data);
			break;
		}

		if (resultFilepath == null || resultFilepath.length() == 0) {
			return;
		}
		updateImg();
	}

	/** 裁剪图片 */
	public boolean doClipPhoto() {
		if (resultFilepath != null && resultFilepath.length() > 0
				&& new File(resultFilepath).exists()) {
			// MyLog.d(PhotoGraph.class, "doClipPhoto:" + resultFilepath);
			CropImageActivity.start(mContext, resultFilepath, REQUEST_MODIFY_FINISH, mStyleId);
			return true;
		}
		return false;
	}

	public void updateImg() {
		dismiss();
		if (resultFilepath != null && resultFilepath.length() > 0) {
			if (mListener != null)
				mListener.onSucess(resultFilepath);
		} else if (mListener != null) {
			mListener.onError("fail");
		}
	}

	/** 获取相册的结果 */
	private String getGalleryImagePath(Intent data) {
		String path = "";
		try {

			Uri originalUri = data.getData(); // 获得图片的uri
			String[] proj = { MediaStore.Images.Media.DATA };
			// 好像是android多媒体数据库的封装接口，具体的看Android文档
			Cursor cursor = mContext.managedQuery(originalUri, proj, null, null, null);
			int column_index = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
			cursor.moveToFirst();
			path = cursor.getString(column_index);
		} catch (Exception e) {
			path = data.getDataString();
		}
		if (path != null && path.length() > 0) {
			path = path.replace("file://", "");
		}
		return path;

	}

	@SuppressLint("NewApi")
	public static String getPath(final Context context, final Uri uri) {

		final boolean isKitKat = Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT;

		// DocumentProvider
		if (isKitKat && DocumentsContract.isDocumentUri(context, uri)) {
			// ExternalStorageProvider
			if (isExternalStorageDocument(uri)) {
				final String docId = DocumentsContract.getDocumentId(uri);
				final String[] split = docId.split(":");
				final String type = split[0];

				if ("primary".equalsIgnoreCase(type)) {
					return Environment.getExternalStorageDirectory() + "/" + split[1];
				}

				// TODO handle non-primary volumes
			}
			// DownloadsProvider
			else if (isDownloadsDocument(uri)) {

				final String id = DocumentsContract.getDocumentId(uri);
				final Uri contentUri = ContentUris.withAppendedId(
						Uri.parse("content://downloads/public_downloads"), Long.valueOf(id));

				return getDataColumn(context, contentUri, null, null);
			}
			// MediaProvider
			else if (isMediaDocument(uri)) {
				final String docId = DocumentsContract.getDocumentId(uri);
				final String[] split = docId.split(":");
				final String type = split[0];

				Uri contentUri = null;
				if ("image".equals(type)) {
					contentUri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI;
				} else if ("video".equals(type)) {
					contentUri = MediaStore.Video.Media.EXTERNAL_CONTENT_URI;
				} else if ("audio".equals(type)) {
					contentUri = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI;
				}

				final String selection = "_id=?";
				final String[] selectionArgs = new String[] { split[1] };

				return getDataColumn(context, contentUri, selection, selectionArgs);
			}
		}
		// MediaStore (and general)
		else if ("content".equalsIgnoreCase(uri.getScheme())) {

			// Return the remote address
			if (isGooglePhotosUri(uri))
				return uri.getLastPathSegment();

			return getDataColumn(context, uri, null, null);
		}
		// File
		else if ("file".equalsIgnoreCase(uri.getScheme())) {
			return uri.getPath();
		}

		return null;
	}

	/**
	 * Get the value of the data column for this Uri. This is useful for
	 * MediaStore Uris, and other file-based ContentProviders.
	 * 
	 * @param context
	 *            The context.
	 * @param uri
	 *            The Uri to query.
	 * @param selection
	 *            (Optional) Filter used in the query.
	 * @param selectionArgs
	 *            (Optional) Selection arguments used in the query.
	 * @return The value of the _data column, which is typically a file path.
	 */
	public static String getDataColumn(Context context, Uri uri, String selection,
			String[] selectionArgs) {

		Cursor cursor = null;
		final String column = "_data";
		final String[] projection = { column };

		try {
			cursor = context.getContentResolver().query(uri, projection, selection, selectionArgs,
					null);
			if (cursor != null && cursor.moveToFirst()) {
				final int index = cursor.getColumnIndexOrThrow(column);
				return cursor.getString(index);
			}
		} finally {
			if (cursor != null)
				cursor.close();
		}
		return null;
	}

	/**
	 * @param uri
	 *            The Uri to check.
	 * @return Whether the Uri authority is ExternalStorageProvider.
	 */
	public static boolean isExternalStorageDocument(Uri uri) {
		return "com.android.externalstorage.documents".equals(uri.getAuthority());
	}

	/**
	 * @param uri
	 *            The Uri to check.
	 * @return Whether the Uri authority is DownloadsProvider.
	 */
	public static boolean isDownloadsDocument(Uri uri) {
		return "com.android.providers.downloads.documents".equals(uri.getAuthority());
	}

	/**
	 * @param uri
	 *            The Uri to check.
	 * @return Whether the Uri authority is MediaProvider.
	 */
	public static boolean isMediaDocument(Uri uri) {
		return "com.android.providers.media.documents".equals(uri.getAuthority());
	}

	/**
	 * @param uri
	 *            The Uri to check.
	 * @return Whether the Uri authority is Google Photos.
	 */
	public static boolean isGooglePhotosUri(Uri uri) {
		return "com.google.android.apps.photos.content".equals(uri.getAuthority());
	}

	/** 处理拍照结果 */
	private void doImg(Intent data) {
		String image_path = data.getDataString();
		resultFilepath = Environment.getExternalStorageDirectory() + mContext.getPackageName()
				+ "/" + Utils.getTime() + ".jpg";
		Bitmap bm = null;
		if (image_path != null && image_path.length() > 0) {
			Uri uri = Uri.parse(image_path);
			try {
				bm = android.provider.MediaStore.Images.Media.getBitmap(
						mContext.getContentResolver(), uri);
			} catch (Exception e1) {
				e1.printStackTrace();
				return;
			}
		} else {
			Bundle extras = data.getExtras();
			bm = (Bitmap) extras.get("data");
		}

		FileOutputStream outStream;
		try {
			File picfile = new File(resultFilepath);
			if (!picfile.getParentFile().exists()) {
				picfile.getParentFile().mkdirs();
				HelperMediaFile.setFilepermission(picfile.getParent());
			}
			outStream = new FileOutputStream(picfile);
			if (null != outStream) {
				// Bitmap.CompressFormat.JPEG降低画面质量
				bm.compress(Bitmap.CompressFormat.JPEG, 100, outStream);
				outStream.close();
			}
			HelperMediaFile.setFilepermission(resultFilepath);
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	@Override
	public boolean onKey(View v, int keyCode, KeyEvent event) {
		// TODO Auto-generated method stub
		if (mKeyCodeBack && event.getAction() == KeyEvent.ACTION_DOWN
				&& keyCode == KeyEvent.KEYCODE_BACK)
			dismiss();
		return false;
	}

}